import time
import base64
import json
import os
import logging
from threading import Thread, Event
from picamera2 import Picamera2
import cv2
import paho.mqtt.client as mqtt
from datetime import datetime
from paho.mqtt.client import CallbackAPIVersion

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("Video")

# MQTT 配置（针对 EMQX）
BROKER = "120.46.12.5"
PORT = 1883
TOPIC = "camera/encode_transfrom"
CLIENT_ID = "raspberry_camera"
USERNAME = "gll"
PASSWORD = "gll55555"

# MQTT 回调函数
def on_connect(client, userdata, flags, reason_code, properties):
    if reason_code == 0:
        logger.info("Connected to EMQX broker")
    else:
        logger.error(f"Failed to connect to EMQX, reason: {reason_code}")

def on_publish(client, userdata, mid, reason_code, properties):
    logger.info(f"Message {mid} published with reason code: {reason_code}")

client = mqtt.Client(client_id=CLIENT_ID, callback_api_version=CallbackAPIVersion.VERSION2)
client.username_pw_set(username=USERNAME, password=PASSWORD)
client.on_connect = on_connect
client.on_publish = on_publish
client.connect(BROKER, PORT, 60)
client.loop_start()

class Video:
    def __init__(self):
        self.cap = Picamera2()
        self.stop_event = Event()
        self.frame_count = 0
        self.fps_start = time.time()
        self.fps = 0
        os.makedirs("IMAGES", exist_ok=True)

    def setup(self):
        config = self.cap.create_video_configuration(
            main={"size": (320, 240)},
            controls={"FrameRate": 15.0}
        )
        self.cap.configure(config)
        self.cap.start()
        time.sleep(1)
        logger.info("Camera started")

    def calculate_fps(self):
        self.frame_count += 1
        elapsed = time.time() - self.fps_start
        if elapsed >= 1.0:
            self.fps = self.frame_count / elapsed
            logger.info(f"FPS: {self.fps:.2f}")
            self.frame_count = 0
            self.fps_start = time.time()

    def stream_to_mqtt(self):
        while not self.stop_event.is_set():
            frame = self.cap.capture_array("main")
            frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)

            # 显示本地窗口 q t
            cv2.imshow("Local stream", frame)

            _, buffer = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, 80])
            image_base64 = base64.b64encode(buffer).decode('utf-8')
            payload = {"image": image_base64, "timestamp": datetime.now().strftime('%Y-%m-%dT%H:%M:%S')}
            json_payload = json.dumps(payload)
            client.publish(TOPIC, json_payload, qos=0)
            self.calculate_fps()
            time.sleep(0.066)

    def take_picture(self):
        filename = f"IMAGES/{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
        buffer = self.cap.capture_array("main")
        buffer = cv2.cvtColor(buffer, cv2.COLOR_RGB2BGR)
        cv2.imwrite(filename, buffer)
        logger.info(f"Saved: {filename}")

    def run(self):
        self.setup()
        stream_thread = Thread(target=self.stream_to_mqtt, daemon=True)
        stream_thread.start()
        try:
            while not self.stop_event.is_set():
                key = cv2.waitKey(1) #需要窗口才能捕获q t 按键
                if key == ord('t'):
                    self.take_picture()
                elif key == ord('q'):
                    self.stop_event.set()
        except KeyboardInterrupt:
            logger.info("Stopped by user")
        finally:
            self.stop_event.set()
            self.cap.stop()
            cv2.destroyAllWindows()
            client.loop_stop()
            client.disconnect()
            logger.info("Camera and MQTT stopped")

if __name__ == "__main__":
    video = Video()
    video.run()